package receive;

import java.util.ArrayList ;
import java.util.Collections ;
import java.util.Date ;
import java.util.List ;

import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;

import org.apache.xml.security.utils.Base64 ;

import agency.sales.C3ftst ;
import common.Card ;
import common.Notify ;
import common.Sequence ;
import common.Service ;
import common.Servlet ;
import common.Validate ;
import dict.BcDict ;
import dict.CommonDict ;
import dict.TransactionDict ;
import dicts.GlobalDict ;
import dicts.PaymentDict ;
import entities.TBank ;
import entities.TBc ;
import entities.TCard ;
import entities.TCs ;
import entities.TMerchant ;
import entities.TMs ;
import entities.TSm ;
import entities.TSubject ;
import entities.TTransaction ;
import interfaces.IBankService ;
import interfaces.IBcService ;
import interfaces.ICardService ;
import interfaces.ICsService ;
import interfaces.IMerchantService ;
import interfaces.IMsService ;
import interfaces.ISmService ;
import interfaces.ISubjectService ;
import interfaces.ITransactionService ;
import net.sf.json.JSONObject ;
import util.LogUtil ;
import utils.DateUtil ;
import utils.DigestUtil ;
import utils.NumberUtil ;
import utils.StringUtil ;

public class C3dtst extends Servlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public synchronized void process(HttpServletRequest request, HttpServletResponse response) throws Exception {

		System.out.println(DateUtil.format(new Date(), DateUtil.DATETIME) + " | 3D验证");
		
		// 初始化service
		ISubjectService subjectService = (ISubjectService) Service.create(ISubjectService.class);
		IMerchantService merchantService = (IMerchantService) Service.create(IMerchantService.class);
		ICardService cardService = (ICardService) Service.create(ICardService.class);
		IBankService bankService = (IBankService) Service.create(IBankService.class);
		ITransactionService transactionService = (ITransactionService) Service.create(ITransactionService.class);
		IBcService bcService = (IBcService) Service.create(IBcService.class);
		ICsService csService = (ICsService) Service.create(ICsService.class);
		ISmService smService = (ISmService) Service.create(ISmService.class);
		IMsService msService = (IMsService) Service.create(IMsService.class);

		JSONObject jsonResult = new JSONObject();

		// 初始化bean和属性
		TBank bank = new TBank();
		TSubject subject = new TSubject();
		TMerchant merchant = new TMerchant();
		TCard card = new TCard();
		TTransaction transaction = new TTransaction();
		TBc bc = new TBc();
		TCs cs = new TCs();
		TSm sm = new TSm();
		TMs ms = new TMs();
		
		// 验证系统
		if (GlobalDict.LINUX.equalsIgnoreCase(System.getProperty("os.name")) && !CommonDict.HOST.equals(request.getServerName())) {
			response.getWriter().print(Validate.result(TransactionDict.ILLAGEL_ACCESS, TransactionDict.MESSAGES.get(TransactionDict.ILLAGEL_ACCESS)));
			return;
		}

		// 校验参数 ( 名称,值,校验模式,边界 )
		List<Object[]> parameterList = Collections.synchronizedList(new ArrayList<Object[]>());
		parameterList.add(new Object[] { "MD", request.getParameter("MD"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 20000  });
		parameterList.add(new Object[] { "PaRes", request.getParameter("PaRes"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 20000  });

		
		JSONObject validateResult = Validate.validate(parameterList);
		LogUtil.check(Validate.summary(parameterList));

		if (!StringUtil.isEmpty(validateResult)) {
			System.out.println ( validateResult.toString() ) ;
			response.getWriter().print(validateResult.toString());
			return;
		}
				
		LogUtil.receive ( "c3dtst", "MD="+ request.getParameter("MD")+"&PaRes="+request.getParameter("PaRes") );	
		
		// 校验入账存在和状态
		try {
			bc = bcService.fetch(request.getParameter("MD"));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(BcDict.BC_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(BcDict.BC_FETCH_EXCEPTION)));
			return;
		}

		if (bc == null) {
			response.getWriter().print(Validate.result(BcDict.BC_NOT_EXIST, TransactionDict.MESSAGES.get(BcDict.BC_NOT_EXIST)));
			return;
		}

		if (bc.getBcState().equals("1")) {
			response.getWriter().print(Validate.result(BcDict.BC_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(BcDict.BC_STATUS_EXCEPTION)));
			return;
		}
	
		// 得到通道对象
		try {
			bank = bankService.fetch(bc.getBnkNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(BcDict.BC_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(BcDict.BC_FETCH_EXCEPTION)));
			return;
		}
		if (bank == null) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_CONFIGURATION_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_CONFIGURATION_EXCEPTION)));
			return;
		}
		if (!bank.getBnkState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.AGENCY_CLOSED, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_CLOSED)));
			return;
		}

		// 校验交易存在和状态
		try {
			transaction = transactionService.fetch(bc.getTxnNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_FETCH_EXCEPTION)));
			return;
		}

		if (transaction == null) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_NOT_EXIST)));
			return;
		}

		if (transaction.getTxnState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_STATUS_EXCEPTION)));
			return;
		}
		
		// 校验子账户存在和状态
		try {
			subject = subjectService.fetch(transaction.getTxnNo().substring(0, 6));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.SUBJECT_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.SUBJECT_FETCH_EXCEPTION)));
			return;
		}

		if (subject == null) {
			response.getWriter().print(Validate.result(TransactionDict.SUBJECT_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.SUBJECT_NOT_EXIST)));
			return;
		}

		if (!subject.getSubState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.SUBJECT_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.SUBJECT_STATUS_EXCEPTION)));
			return;
		}
		
		// 交易商户存在和状态
		try {
			merchant = merchantService.fetch(transaction.getMerNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_FETCH_EXCEPTION)));
			return;
		}

		if (merchant == null) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_NOT_EXIST)));
			return;
		}

		if (!merchant.getMerState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_STATUS_EXCEPTION)));
			return;
		}
		
		
		// 持卡人存在和状态
		try {
			card = cardService.fetch(transaction.getCrdNo());
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.CARD_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CARD_FETCH_EXCEPTION)));
			return;
		}

		if (card == null) {
			response.getWriter().print(Validate.result(TransactionDict.CARD_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.CARD_NOT_EXIST)));
			return;
		}

		if (!card.getCrdState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.CARD_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CARD_STATUS_EXCEPTION)));
			return;
		}

		
		try {
			new C3ftst().process ( bc , transaction , bank , card );
			bcService.persist(bc);
		} catch (Exception e) {
			response.getWriter().print(Validate.result(BcDict.BC_PROCESS_EXCEPTION, BcDict.MESSAGES.get(BcDict.BC_PROCESS_EXCEPTION)));
			return;
		}
		
		// 提交上游处理完成后根据收单状态进行清结算
		if (bc.getBcState().equals("1")) {
			if (merchant.getMerShipping().equals("1")) {
				transaction.setTxnLogic("1");
			}
			transaction.setTxnState("1");
			transactionService.persist(transaction);

			cs.setCsNo(Sequence.csSequence());
			cs.setCrdNo(card.getCrdNo());
			cs.setTxnNo(transaction.getTxnNo());
			cs.setCsType(PaymentDict.CS_DEALAGE);
			cs.setCsAmount(transaction.getTxnAmount());
			cs.setCsState("1");
			cs.setCsDate(new Date());
			csService.persist(cs);

			cs.setCsNo(Sequence.csSequence());
			cs.setCrdNo(card.getCrdNo());
			cs.setTxnNo(transaction.getTxnNo());
			cs.setCsType(PaymentDict.CS_MARKUP);
			cs.setCsAmount(NumberUtil.sub(bc.getBcAmount(), transaction.getTxnAmount()));
			cs.setCsState("1");
			cs.setCsDate(new Date());
			csService.persist(cs);

			sm.setSmNo(Sequence.smSequence());
			sm.setMerNo(merchant.getMerNo());
			sm.setTxnNo(transaction.getTxnNo());
			sm.setSmType(PaymentDict.SM_THANSFER);
			sm.setSmAmount(transaction.getTxnAmount());
			sm.setSmState("1");
			sm.setSmDate(new Date());
			smService.persist(sm);

			ms.setMsNo(Sequence.msSequence());
			ms.setMerNo(merchant.getMerNo());
			ms.setTxnNo(transaction.getTxnNo());
			ms.setMsType(PaymentDict.MS_POUNDAGE);
			ms.setMsAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(Card.toPoundage(card.getCrdNumber(), merchant), new Double(100), 4)));
			ms.setMsState("1");
			ms.setMsDate(new Date());
			msService.persist(ms);

			ms.setMsNo(Sequence.msSequence());
			ms.setMerNo(merchant.getMerNo());
			ms.setTxnNo(transaction.getTxnNo());
			ms.setMsType(PaymentDict.MS_MORTGAGE);
			ms.setMsAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(Card.toMortgage(card.getCrdNumber(), merchant), new Double(100), 4)));
			ms.setMsState("1");
			ms.setMsDate(new Date());
			msService.persist(ms);

			sm.setSmNo(Sequence.smSequence());
			sm.setMerNo(merchant.getMerNo());
			sm.setTxnNo(transaction.getTxnNo());
			sm.setSmType(PaymentDict.SM_MORTGAGE);
			sm.setSmAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(Card.toMortgage(card.getCrdNumber(), merchant), new Double(100), 4)));
			sm.setSmState("0");
			sm.setSmDate(new Date(new Date().getTime() + NumberUtil.mul(merchant.getMerReturn(), GlobalDict.DAY.doubleValue()).longValue()));
			smService.persist(sm);
		}

		jsonResult.put("version", GlobalDict.VERSION);
		jsonResult.put("no", subject.getSubNo());
		jsonResult.put("transaction", transaction.getTxnNo());
		jsonResult.put("order", transaction.getTxnOrder());
		jsonResult.put("cur", transaction.getTxnCur());
		jsonResult.put("loc", NumberUtil.transfer(transaction.getTxnLoc()));
		jsonResult.put("rate", NumberUtil.transfer(transaction.getTxnRate(), 4));
		jsonResult.put("amount", NumberUtil.transfer(transaction.getTxnAmount()));
		jsonResult.put("issue", bank.getBnkBill());
		// 如果交易失败
		if (transaction.getTxnState().equals("0")) {
			jsonResult.put("code", bc.getBcCode());
			jsonResult.put("message", bc.getBcMessage());
			jsonResult.put("signature", DigestUtil.sha256(GlobalDict.VERSION+subject.getSubNo() + transaction.getTxnOrder() + NumberUtil.transfer(transaction.getTxnAmount ( )) +jsonResult.getString ( "code" )+ subject.getSubKey()));
			// 设置了失败通知
			if (merchant.getMerNotifying().equals("1")) {
				Notify.assembly(transaction.getTxnNotify(), jsonResult);
				LogUtil.notify ( Notify.redirect ( transaction.getTxnNotify(), jsonResult ) );
			}
			response.sendRedirect ( Notify.redirect (transaction.getTxnNotify(), jsonResult) );
			return;
		}
		// 如果交易成功
		jsonResult.put("code", TransactionDict.TRANSACTION_SUCCESS);
		jsonResult.put("message", TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_SUCCESS));
		jsonResult.put("signature", DigestUtil.sha256(GlobalDict.VERSION+subject.getSubNo() + transaction.getTxnOrder() + NumberUtil.transfer(transaction.getTxnAmount ( )) +jsonResult.getString ( "code" )+ subject.getSubKey()));
		Notify.assembly(transaction.getTxnNotify(), jsonResult);
		LogUtil.notify ( Notify.redirect ( transaction.getTxnNotify(), jsonResult ) );
		
		response.sendRedirect ( Notify.redirect (transaction.getTxnNotify(), jsonResult) );
		return;
	}
		
	
	public static void main  (
			String [ ] args
	)throws Exception
	{
		String s="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";
		
		byte[] b=Base64.decode ( s );
		
		System.out.println ( new String(b,"UTF-8") ) ;
		
		
	}
}